/*************************************************************************
 *
 *  Copyright (C) 2013 Florian Dang <florian.coin@gmail.com>
 *
 *  This file is part of NatusVerse.
 *
 *  NatusVerse is free software: you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation, either version 3 of the License, or
 *  (at your option) any later version.
 *
 *  NatusVerse is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with NatusVerse.  If not, see <http://www.gnu.org/licenses/>.
 *
 *************************************************************************/

#include "nbody/body.h"
#include "graphics/geometry.h"
using graphics::Circle;
using graphics::Graphics;

namespace nbody
{
const float Body::kGravityConst     = 6.67e-2f; // 0.8f;
const float Body::kEpsCollision     = 1.0e1f;
const int   Body::kMaxParticleSize  = 800;
const bool  Body::kRebounce         = true;

typedef Graphics::t_point t_point;
typedef Graphics::t_vector t_vector;

void Body::Move(t_vector f, float dt)
{
	t_vector a;
	a.x = f.x / mass_;
	a.y = f.y / mass_;

	velocity_.x += dt * a.x;
	velocity_.y += dt * a.y;

	center_.x += dt * velocity_.x;
	center_.y += dt * velocity_.y;
}


void Body::Draw(Graphics win)
{
	int radius = 2 + mass_ / 200;
	Circle c(win, center_, radius, color_);

	if (kRebounce == true)
	{
		std::cout << center_.x << ":" << center_.y << "\t";
		if(center_.x <= 1 || center_.x >= win.GetW() - 1)
			velocity_.x *= -1.0f;
		if(center_.y <= 1 || center_.y >= win.GetH() - 1)
			velocity_.y *= -1.0f;
	}

	c.DrawFill();
}

void Body::Erase(Graphics win)
{
	int radius = 2 + mass_ / 200;

	Circle c(win, center_, radius, color_);
	c.Erase();
}

void Body::ChangeColor()
{
	int r, g, b;
	b = (color_) & 255;
	g = (color_ >> 8) & 255;
	r = (color_ >> 16) & 255;

	r += Rand::RInt(-1, 3);
	g += Rand::RInt(-1, 3);
	b += Rand::RInt(-1, 3);

	color_ = color::Color::ColorRGB(r, g, b);
}

t_vector Body::ForceFrom(Body body)
{
	t_vector delta;
	delta.x = body.center().x - center_.x;
	delta.y = body.center().y - center_.y;

	float dist = Graphics::Distance(body.center(), center_);

	float F = (kGravityConst * mass_ * body.mass()) /
	          ((dist * dist) + (kEpsCollision * kEpsCollision));

	delta.x = delta.x / dist * F;
	delta.y = delta.y / dist * F;

	return delta;
}
} // end namespace
